package it.univpm.diiga.semanticsearch.configurazione;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;

import static java.util.concurrent.TimeUnit.*;




public class Configuration {

	 private static String configLocalURL="webapps/webids/localConfig.xml"; //URL FILE DI CONFIGURAZIONE
	 private static List<URL> publicRepoLink;
	 private static List<URL> defaultRepoLink;
	 private static List<URL> localRepoLink;
	 private static List<File> localRepoFile;
	 
	 
	 
	 private static Hashtable<String, Object> configuration = new Hashtable<String, Object>();
	
	 public static List<URL> getDefaultRepoLink(){
		   return (List<URL>) configuration.get("defaultRepoLink");
	   }
	 
	 public static List<URL> getPublicRepoLink(){
		 return (List<URL>) configuration.get("publicRepoLink");
	 }
	 
	 public static File getLocalRepoLink(){
		 return  new File((String) configuration.get("localRepoLink"));
	 }
	 
	 public static String getLocalRepoFormat(){
		 return (String) configuration.get("formatLocalRepository");
	 }
	 
	 
	 public static Hashtable getConfiguration(){
		   return configuration;
	   }
	 
	 public static boolean isSetProxy(){
		 if (configuration.get("proxyEnabled").toString().equalsIgnoreCase("yes")){
			 return true;
		 }
		 return false;
	 }
	 
	 public static int getnOfSearch(){
		 //return "ciao";
		 return Integer.parseInt((String)configuration.get("nOfSearch"));
	 }
	 
	 public static int getnOfCut(){
		 return Integer.parseInt((String)configuration.get("nOfCut"));
	 }
	 
	 public static int getIndexServ(){
		 return Integer.parseInt((String)configuration.get("indexServ"));
	 }
	 
	 public static int getSave(){
		 return Integer.parseInt((String)configuration.get("save"));
	 }
	 
	 public static TimeUnit getUnit(){
		 //return "ciao";
		 
		 //String unit=null;
		 if (configuration.get("unit").equals("HOURS"))
			 return HOURS;
		 else if (configuration.get("unit").equals("MINUTES"))
			 return MINUTES;
		 else if (configuration.get("unit").equals("SECONDS"))
			 return SECONDS;
		 else 
			 	return DAYS;

	 }
	 
	 public static int getPeriod(){
		 return Integer.parseInt((String)configuration.get("period"));
	 }
	 
	 
	 public static Hashtable getAllConfiguration() throws Exception{
		  boolean repoconfig=findRepoConfiguration();
		   boolean localconfig=findLocalConfiguration();
		   
		  // boolean rankConfiguration=findRankConfiguration();
		   
		   if ( repoconfig && localconfig)
			   throw new FileConfigExc();
		   if (repoconfig)
			   throw new RemoteExc();
		   if (localconfig)
			   throw new LocalExc();
		   return configuration;
	   }
	
	 
	
	 
	 
	public static boolean findRepoConfiguration() throws  Exception{
		  // Document document=null;
			publicRepoLink=new ArrayList<URL>();
			defaultRepoLink=new ArrayList<URL>();
			
		   boolean repoexc=false;
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
		
				DocumentBuilder db = dbf.newDocumentBuilder();
				try{

						Document document = db.parse(configLocalURL);
						Element rootEle = document.getDocumentElement(); //config
						
						//RECUPERO REPOSITORY
						NodeList list_serv = rootEle.getElementsByTagName("repository");
						if (list_serv.getLength()==0){
							return true;
						}
						for(int i = 0 ; i < list_serv.getLength();i++) {
		
							Element service = (Element)list_serv.item(i);
				            
							
							NodeList list_ele = service.getElementsByTagName("public");
				            if(list_ele != null && list_ele.getLength() > 0) {
				                Element ele = (Element)list_ele.item(0);
				                if (ele.hasChildNodes()){ // if node exist
				                 publicRepoLink.add(new URL(ele.getFirstChild().getNodeValue())); //link public
				     			configuration.put("publicRepoLink", publicRepoLink);
				     			
				                }
				               
				            }
				            else{
				            	 repoexc=true;
				            	 
				            }
				            
				            list_ele = service.getElementsByTagName("default");
				            if(list_ele != null && list_ele.getLength() > 0) {
				            	for (int j=0; j<list_ele.getLength(); j++){
				            		Element ele = (Element)list_ele.item(j);
				            		if (ele.hasChildNodes()){ // if node exist
				            			defaultRepoLink.add(new URL(ele.getFirstChild().getNodeValue()));		
				            		}
				            	}
				            	configuration.put("defaultRepoLink", defaultRepoLink);
				            }else{
				            	repoexc=true;
				            	
				            }
				            	  		 
						}
						
						
						/*if (repoexc)
							throw new RemoteExc();*/
				}catch(Exception e){
					System.out.println("remote exc");
					throw new RemoteExc();
				}
				return repoexc;
		   
	   }
	   
	   public static boolean findLocalConfiguration() throws Exception{
		   	localRepoLink=new ArrayList<URL>();
		   	localRepoFile=new ArrayList<File>();
		   	boolean proxyexc=false;
		   	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
			
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document=null;
			//try{
					document = db.parse(new File(configLocalURL));
			   		
					Element rootEle = document.getDocumentElement(); //config
				   
					
				   
				 //RECUPERO PROXY INFO
					NodeList proxy_setting = rootEle.getElementsByTagName("proxy");
					if (proxy_setting.getLength()==0){
						return true;
					}
					for(int i = 0 ; i < proxy_setting.getLength();i++) {
		
						Element service = (Element)proxy_setting.item(i);
			           
						
					   NodeList list_ele = service.getElementsByTagName("address");
			           if(list_ele != null && list_ele.getLength() > 0) {
			               Element ele = (Element)list_ele.item(0);
			               if (ele.hasChildNodes()){ // if node exist
			               	configuration.put("proxyAddress", ele.getFirstChild().getNodeValue());
			               }
			               else
			            	   configuration.put("proxyAddress", "");
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("port");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("proxyPort", ele.getFirstChild().getNodeValue());
			           			
			           		} else
			           			configuration.put("proxyPort", "");
			           	}
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("enabled");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("proxyEnabled", ele.getFirstChild().getNodeValue());
			           			if (ele.getFirstChild().getNodeValue().equalsIgnoreCase("yes")){
			           				System.getProperties().put( "proxySet", "true" );
			           				String address= configuration.get("proxyAddress").toString();
			           				String port=configuration.get("proxyPort").toString();
			           				if (!proxyexc){
			           					System.getProperties().put( "proxyHost", configuration.get("proxyAddress").toString() );
			           					System.getProperties().put( "proxyPort", configuration.get("proxyPort").toString());
			           				}
			           			}
			           			else{
			           				System.getProperties().put( "proxySet", "false" );
			           				System.getProperties().put( "proxyHost", "" );
		           					System.getProperties().put( "proxyPort", "");
			           			}
			           		}
			           	}
			           }
			           else{
			        	  proxyexc=true;
			           }
			                       		 
					}
					
					
					//RECUPERO LOCAL REPO SETTINGS
					NodeList repository_setting = rootEle.getElementsByTagName("repository");
					if (repository_setting.getLength()==0){
						return true;
					}
					for(int i = 0 ; i < repository_setting.getLength();i++) {
		
						Element service = (Element)repository_setting.item(i);
			           
						
					   NodeList list_ele = service.getElementsByTagName("link");
					   
					   
					   
					   
			           if(list_ele != null && list_ele.getLength() > 0) {
			               Element ele = (Element)list_ele.item(0);
			               if (ele.hasChildNodes()){ // if node exist
			                	File file=new File(ele.getFirstChild().getNodeValue());
			                	if (!file.exists()){
			                		proxyexc=true;
			                		configuration.put("localRepoLink","");
			                	}else{
			                		configuration.put("localRepoLink",file.getAbsolutePath());
			                	}
			               }
			               else{
			            	   configuration.put("localRepoLink","");
			               }
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("format");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("localRepoFormat", ele.getFirstChild().getNodeValue());
			           			
			           		}
			           		else{
			           			configuration.put("localRepoFormat","xml");
			           		}
			           	}
			           }
			           else{
			        	   proxyexc=true;
			           }
			                       		 
					}
			/*}catch(Exception e){
	   			System.out.println("local exc");
	   			throw new LocalExc();
	   		}*/
			
			return proxyexc; 

	   }
	   
	   
	   
		 
		public static void findRankConfiguration() throws  Exception{
			   
			   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
			
					DocumentBuilder db = dbf.newDocumentBuilder();
					

					try{
	
							
							
							Document document = db.parse(new File(configLocalURL));
							

							
							
				
							Element rootEle = document.getDocumentElement(); //config
							
							//RECUPERO REPOSITORY
							NodeList list_serv = rootEle.getElementsByTagName("rank");
							if (list_serv.getLength()==0){
							
							}
							for(int i = 0 ; i < list_serv.getLength();i++) {
			
								Element service = (Element)list_serv.item(i);
					            
								// numero di servizi da indicizzare durante la ricerca
								NodeList list_ele = service.getElementsByTagName("nOfSearch");
					            if(list_ele != null && list_ele.getLength() > 0) {
					                Element ele = (Element)list_ele.item(0);
					                if (ele.hasChildNodes()){ // if node exist
					                	String nOfSearch=ele.getFirstChild().getNodeValue();
					                	configuration.put("nOfSearch", nOfSearch);					     			
					                }else{
					                	configuration.put("nOfSearch", "nada di nada");
					                }
					               
					            }
					            else{
					            	 
					            }
					            // numero di servizi a cui limitare rank.xml
					            list_ele = service.getElementsByTagName("nOfCut");
					            if(list_ele != null && list_ele.getLength() > 0) {
					       
					            		Element ele = (Element)list_ele.item(0);
					            		if (ele.hasChildNodes()){ // if node exist
						                	String nOfCut=ele.getFirstChild().getNodeValue();
						                	configuration.put("nOfCut", nOfCut);	
					            		}else{
					            			configuration.put("nOfCut", "nada di nada");
					            		}
					            }else{
					            	
					            }
					            
					            // valore da assegnare al servizio per l'indicizzazione in seguito alla ricerca
					            list_ele = service.getElementsByTagName("indexServ");
					            if(list_ele != null && list_ele.getLength() > 0) {
					       
					            		Element ele = (Element)list_ele.item(0);
					            		if (ele.hasChildNodes()){ // if node exist
						                	String indexServ=ele.getFirstChild().getNodeValue();
						                	configuration.put("indexServ", indexServ);	
					            		}else{
					            			configuration.put("indexServ", "nada di nada");
					            		}
					            }else{
					            	
					            }
					            
					            // valore da assegnare dopo l'apertura/salvataggio del file
					            list_ele = service.getElementsByTagName("save");
					            if(list_ele != null && list_ele.getLength() > 0) {
					       
					            		Element ele = (Element)list_ele.item(0);
					            		if (ele.hasChildNodes()){ // if node exist
						                	String save=ele.getFirstChild().getNodeValue();
						                	configuration.put("save", save);	
					            		}else{
					            			configuration.put("save", "nada di nada");
					            		}
					            }else{
					            	
					            }
					            
					            
					            	  		 
							}
							
							
							/*if (repoexc)
								throw new RemoteExc();*/
					}catch(Exception e){
						System.out.println("rank exc");
						throw new LocalExc();
					}
					
			   
		   }
	   

		
		public static void findDaemonConfiguration() throws  Exception{		   
		   
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
		
				DocumentBuilder db = dbf.newDocumentBuilder();

				try{

						Document document = db.parse(new File(configLocalURL));

						Element rootEle = document.getDocumentElement(); //config
						
						//RECUPERO REPOSITORY
						NodeList list_serv = rootEle.getElementsByTagName("daemon");
						if (list_serv.getLength()==0){
						
						}
						for(int i = 0 ; i < list_serv.getLength();i++) {
		
							Element service = (Element)list_serv.item(i);
				            
							
							NodeList list_ele = service.getElementsByTagName("period");
				            if(list_ele != null && list_ele.getLength() > 0) {
				                Element ele = (Element)list_ele.item(0);
				                if (ele.hasChildNodes()){ // if node exist
				                	String period=ele.getFirstChild().getNodeValue();
				                	configuration.put("period", period);					     			
				                }else{
				                	configuration.put("period", "nada di nada");
				                }
				               
				            }
				            else{
				            	 
				            }
				            
				            list_ele = service.getElementsByTagName("unit");
				            if(list_ele != null && list_ele.getLength() > 0) {
				       
				            		Element ele = (Element)list_ele.item(0);
				            		if (ele.hasChildNodes()){ // if node exist
					                	String unit=ele.getFirstChild().getNodeValue();
					                	configuration.put("unit", unit);	
				            		}else{
				            			configuration.put("unit", "nada di nada");
				            		}
				            }else{
				            	
				            }
				            	  		 
						}
						
						
						/*if (repoexc)
							throw new RemoteExc();*/
				}catch(Exception e){
					System.out.println("daemon exc");
					throw new LocalExc();
				}
				
		   
	   }
	   
	   
	   
	   public static void setNewConfiguration(String parentTag,String parameterTag,String value) throws Exception{
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
			DocumentBuilder db = dbf.newDocumentBuilder();
			File file=new File(configLocalURL);
		    Document document = db.parse(file);
		   Element rootEle = document.getDocumentElement();
		    //int paraSize=para.length;
			NodeList list_serv = rootEle.getElementsByTagName(parentTag);
			for(int i = 0 ; i < list_serv.getLength();i++) {

				Element service = (Element)list_serv.item(i);

					NodeList list_ele = service.getElementsByTagName(parameterTag);
		            if(list_ele != null && list_ele.getLength() > 0) {
		               Element ele = (Element)list_ele.item(0);
		               if (ele.hasChildNodes()){ // if node exist
		            	   if (value.equals("") || value==null)
		            		   ele.getFirstChild().setNodeValue("");
		            	   else
		            		   ele.getFirstChild().setNodeValue(value);
		               }
		               else{
		            	   ele.setTextContent(value);
		  
		               }
		           }
			
	       
	                      		 
			}
			
			   //setting up a transformer
		    TransformerFactory transfac = TransformerFactory.newInstance();
		    Transformer trans = null;
			try {
				trans = transfac.newTransformer();
			} catch (TransformerConfigurationException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		 
		    //generating string from xml tree
		    StringWriter sw = new StringWriter();
		    StreamResult result = new StreamResult(sw);
		    DOMSource source = new DOMSource(document);
		    try {
				trans.transform(source, result);
			} catch (TransformerException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		    String xmlString = sw.toString();
			
			OutputStream f0 = null;
			byte buf[] = xmlString.getBytes();
		    try {
		    	/*URL url;
				url = new URL(this.configLocalURL);
				URLConnection uc=url.openConnection();
				uc.setConnectTimeout(10000);
				uc.connect();*/
				f0 = new FileOutputStream(file);
				 for(int i=0;i<buf .length;i++) {
					 	f0.write(buf[i]);
					    }
						f0.close();
						buf = null;
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		   
	   }
	   
	   public static String getLocalPath(){
		   String path=configLocalURL;
		   return path;
		   
	   }
	   
	   /*
	    * ECCEZIONI
	    */
	  
	   
	   public static class RemoteExc extends FileConfigExc {

			public RemoteExc() {
		// Il costruttore di Exception chiamato inizializza la
		// variabile privata message
		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	   
	   
	   public static class FileConfigExc extends Exception {
		    public FileConfigExc() {
		// Il costruttore di Exception chiamato inizializza la
		// variabile privata message
		        super("Impossibile trovare il repository di default");
		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	   public static class LocalExc extends FileConfigExc {
		    public LocalExc() {
		// Il costruttore di Exception chiamato inizializza la
		// variabile privata message
		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	
}
